let row;
let column;
let maze;

const canvasWidth = document.querySelector(".container").clientWidth;
const canvasHeight = canvasWidth;

let cellWidth;
let cellHeight;

let keyTimer;
let lastKey = null;
let gameTimer;
let gameTimerCounter = 0;
// 0 移动 1 胜利 2 失败
let music = [];
let level = null;

function getRandom(num) {
	return Math.floor(Math.random() * num)
}

class Maze {
	constructor(map) {
		this.map = map;
		this.goneRooms = [];
		this.emptyRooms = JSON.parse(JSON.stringify(map.cells));
		this.current = 0;
	}
	clearWall(start, index) {
		let i = index - start;
		if (i > 0) {
			if (i > 1) {
				this.map.cells[index].top = 0;
			} else {
				this.map.cells[index].left = 0;
			}
		} else {
			if (i < -1) {
				this.map.cells[start].top = 0;
			} else {
				this.map.cells[start].left = 0;
			}
		}
	}
	// 随机一个 与没到过的房间相邻 的 到过的房间
	getNearEmptyRoom() {
		let res = [];
		// 不能传送回原地
		for (let i = 0; i < this.goneRooms.length - 1; i++) {
			// 1 注意这里写得不好，因为 push 的时候把整个数组（只含有一个元素） push 进 goneRooms 了，而不是把单个元素 push 进去
			// const index = this.goneRooms[i][0].index;
			const index = this.goneRooms[i].index;
			if (this.map.lookArround(index).length > 0) {
				res.push(index);
			}
		}
		return res[getRandom(res.length)];
	}
	findIndex(index) {
		for (let i = 0; i < this.emptyRooms.length; i++) {
			if (this.emptyRooms[i].index == index) {
				return i;
			}
		}
	}
	makeMaze() {
		// 起点
		let start = 0;
		this.map.cells[0].gone = 1;
		// 1 splice 返回的是数组 this.goneRooms.push(this.emptyRooms.splice(0, 1));
		this.goneRooms.push(this.emptyRooms.splice(0, 1)[0]);
		// 出口
		let stop = this.map.cells.length - 1;

		// 如果所有房间都去过了，就结束循环
		while (this.emptyRooms.length > 0) {
			let rooms = this.map.lookArround(start);
			// console.log(rooms);
			let index = null;
			// 如果进了死胡同，就传送
			if (rooms.length == 0 || start == stop) {
				start = this.getNearEmptyRoom();
				// console.log('传送到' + start);
				// 传送过去重新开始砸墙
				continue
			} else {
				// 隔壁有房间未经过时，才可以砸通往该房间的墙
				index = rooms[getRandom(rooms.length)];
				// console.log(index);
				// 移动到该位置，并且砸一堵墙
				this.clearWall(start, index);
			}
			// 记住已经移动到新位置了
			start = index;
			this.map.cells[start].gone = 1;
			let room = this.emptyRooms.splice(this.findIndex(start), 1);
			// 1 this.goneRooms.push(room);
			this.goneRooms.push(room[0]);
		}

		this.draw()
	}
	draw() {
		let ul = document.body.querySelector("ul");
		let lis = [];
		for (let i = 0; i < this.map.cells.length; i++) {
			let element = document.createElement("li");

			// element.style.width = `${canvasWidth / column}px`;
			// element.style.height = `${canvasHeight / row}px`;
			element.style.width = `${cellWidth}px`;
			element.style.height = `${cellHeight}px`;

			const cell = this.map.cells[i];
			if (cell.top) {
				element.style.borderTop = "1px solid white";
			}
			if (cell.left) {
				element.style.borderLeft = "1px solid white";
			}
			if (cell.bottom) {
				element.style.borderBottom = "1px solid white";
			}
			if (cell.right) {
				element.style.borderRight = "1px solid white";
			}
			lis.push(element)
		}
		ul.append(...lis);
		ul.firstElementChild.classList.add("current");
		ul.lastElementChild.classList.add("exit");
	}
}

class Map {
	constructor(row, column) {
		this.cells = [];
		for (let i = 0; i < row * column; i++) {
			this.cells.push(new Cell(i));
		}
	}
	// 找未去过的房间
	lookArround(index) {
		let res = [];
		// 上边有房间
		if (index > column - 1) {
			if (!this.cells[index - column].gone) {
				res.push(index - column);
			}
		}
		// 右边有房间
		if ((index + 1) % column != 0) {
			if (!this.cells[index + 1].gone) {
				res.push(index + 1);
			}
		}
		// 下边有房间
		if (index < (row - 1) * column) {
			if (!this.cells[index + column].gone) {
				res.push(index + column);
			}
		}
		// 左边有房间
		if (index % column > 0) {
			if (!this.cells[index - 1].gone) {
				res.push(index - 1);
			}
		}
		return res;
	}

}

class Cell {
	constructor(index) {
		this.index = index;
		// 未到过的房间
		this.gone = 0;
		// 房间的墙 1 表示存在
		this.top = 1;
		this.left = 1;
		if ((index + 1) % column === 0) {
			this.right = 1;
		}
		if (index >= (row - 1) * column) {
			this.bottom = 1;
		}
	}
}

function startGame() {
	let inp = document.querySelectorAll('input');
	const gameTimerBox = document.querySelector('.timer span');
	for (let i = 0; i < inp.length; i++) {
		if (inp[i].checked) {
			level = i;
			row = 10 + i * 5;
			column = 10 + i * 5;
			cellWidth = canvasWidth / row;
			cellHeight = canvasHeight / column;
			maze = new Maze(new Map(row, column));
			maze.makeMaze();
			document.querySelector('.container').style.opacity = "1";
			window.addEventListener("keydown", saveKey);
			window.addEventListener("keyup", clearKey);
			window.addEventListener("touchend", handleTouch);
			document.querySelector('.choose').style.display = "none";

			gameTimerCounter = row + column;
			gameTimerBox.innerText = gameTimerCounter;
			// 开启定时器
			if (!gameTimer) {
				gameTimer = setInterval(() => {
					gameTimerCounter--;
					if (gameTimerCounter > 0) {
						gameTimerBox.innerText = gameTimerCounter;
					} else {
						checkWin();
						clearInterval(gameTimer);
						gameTimer = null;
					}
				}, 1000);
			}
			// 加载音乐
			loadMusic('move.mp3')
			loadMusic('win.mp3')
			loadMusic('lost.mp3')
		}
	}
}

function loadMusic(src) {
	let au = new Audio;
	au.src = src;
	music.push(au)
}

function saveKey(e) {
	let key = e.key;
	if (!lastKey) {
		lastKey = key;
		if (!keyTimer) {
			moveHero(lastKey);
			keyTimer = setInterval(() => {
				if (!checkWin()) {
					moveHero(lastKey);
				}
			}, 200)
		}
	}
}
function moveHero(direction) {
	let ul = document.body.querySelector("ul");
	let current = maze.current;
	switch (direction) {
		case "ArrowUp":
			if (!maze.map.cells[current].top) {
				ul.children[current].classList.remove("current");
				ul.children[current - column].classList.add("current");
				maze.current = current - column;
			}
			break;
		case "ArrowDown":
			if ((current < (row - 1) * column) && (!maze.map.cells[current + column].top)) {
				ul.children[current].classList.remove("current");
				ul.children[current + column].classList.add("current");
				maze.current = current + column;
			}
			break;
		case "ArrowLeft":
			if (!maze.map.cells[current].left) {
				ul.children[current].classList.remove("current");
				ul.children[current - 1].classList.add("current");
				maze.current = current - 1;
			}
			break;
		case "ArrowRight":
			if (((current + 1 % column) != 0) && (!maze.map.cells[current + 1].left)) {
				ul.children[current].classList.remove("current");
				ul.children[current + 1].classList.add("current");
				maze.current = current + 1;
			}
			break;
		default:
			break;
	}
	// 播放移动音乐
	if (music[0].played) {
		music[0].currentTime = 0;
	}
	music[0].play();
	checkWin();
}
// 监听键盘
function clearKey(e) {
	let key = e.key;
	if (key == lastKey) {
		lastKey = null;
		clearInterval(keyTimer);
		keyTimer = null;
	}
}
function checkWin() {
	let box = document.querySelector('.choose');
	if (gameTimerCounter <= 0) {
		// 播放失败音乐
		music[2].play()
		// 显示失败画面
		box.innerHTML = "You Lost !<br>点击此处<br>再来一局";
	} else {
		if (maze.current != (row * column - 1)) {
			return false;
		}
		box.innerHTML = "You Win !<br>点击此处<br>再来一局";
		// 播放胜利音乐
		music[1].play()
	}
	document.querySelector('.container').style.opacity = "0";
	box.style.display = "block";
	box.style.fontSize = "36px";
	box.onclick = (e) => { window.location.reload(); }
	window.removeEventListener("keydown", saveKey);
	window.removeEventListener("keyup", clearKey);
	window.removeEventListener("touchend", handleTouch);

	// 显示排行榜信息
	// loadJSON('https:www.zengwangcheng.com/game/maze_hero_list.json', data => {
	// 	let _ = data;
	// 	if (data[level].scores > gameTimerCounter) {
	// 		// 上传新记录
	// 		_[level].name = "测试人员1";
	// 		_[level].scores = gameTimerCounter;
	// 		// 
	// 	}
	// 	box.append(_)
	// });

	clearInterval(keyTimer);
	clearInterval(gameTimer);
	return true;
}
function loadJSON(url, onsuccess) {
	var request = new XMLHttpRequest();
	request.onreadystatechange = function () {
		if ((request.readyState == 4) && (request.status == 200)) // if DONE and SUCCESS
			onsuccess(JSON.parse(request.responseText));
	}
	request.open("GET", url, true);
	request.send();
}
// 监听触屏
function handleTouch(e) {
	let posi = null;
	console.log(e.changedTouches[0]);
	if (e.changedTouches[0].clientY > window.innerHeight * 0.6) {
		if (e.changedTouches[0].clientX < window.innerWidth * 0.33) {
			posi = "ArrowLeft";
		} else if (e.changedTouches[0].clientX > window.innerWidth * 0.66) {
			posi = "ArrowRight";
		} else {
			if (e.changedTouches[0].clientY > window.innerHeight * 0.8) {
				posi = "ArrowDown";
			} else {
				posi = "ArrowUp";
			}
		}
	}
	moveHero(posi);
}